#include "log.h"

#include <QCoreApplication>
#include <QDateTime>
#include <QMutex>
#include <QDir>
#include <QFile>

static const int MAX_LOG_FILE_SIZE = 4 * 1024 * 1024;

#pragma execution_character_set("utf-8")

int Log::m_logLevel = 0;
QString Log::m_appName = "";
QString Log::m_logDir = "";

Log::Log(int logLevel, const QString &appName, const QString &dir)
{
    m_logLevel = logLevel;
    if (m_logLevel > 4 || m_logLevel < 0)
        m_logLevel = 0;
    m_appName = appName;
    if (m_appName.isEmpty())
        m_appName = "log";
    m_logDir = dir;
    if (m_logDir.isEmpty())
        m_logDir = QCoreApplication::applicationDirPath();

    qInstallMessageHandler(messageOutPut);
}

void Log::messageOutPut(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    // 可配置LOG_LEVEL值，设置输出日志等级，输出等级以下的消息会被跳过
    if (type < m_logLevel) {
        return;
    }
    QString location = QString("%1::%2 第%3行 ").arg(context.file).arg(context.function).arg(context.line);
    QString outputMsg = location + msg;
    switch (type) {
    case QtDebugMsg:// 调试消息0
        outputMsg = "[Debug]-" + location + msg;
        writeToFile(outputMsg.toUtf8().constData());
        break;
    case QtWarningMsg:// 警告消息1
        outputMsg = "[Warnning]-" + location + msg;
        writeToFile(outputMsg.toUtf8().constData());
        break;
    case QtCriticalMsg:// 危险消息2
        outputMsg = "[Critical]-" + location + msg;
        writeToFile(outputMsg.toUtf8().constData());
        break;
    case QtFatalMsg:// 致命错误3
        outputMsg = "[Fatal]-" + location + msg;
        writeToFile(outputMsg.toUtf8().constData());
        abort();
    case QtInfoMsg:// 值得报告的一般消息4
        outputMsg = "[Info]-" + location + msg;
        writeToFile(outputMsg.toUtf8().constData());
        break;
    }
}

void Log::writeToFile(const QByteArray &log)
{
    static QMutex mutex;

    mutex.lock();
    QString logsDir = m_logDir + "/logs/";
    QDir dir;
    if (!dir.exists(logsDir))
    {
        dir.mkdir(logsDir);
    }
    QString dateSuffix = QDateTime::currentDateTime().toString("_yyyy_MM_dd");
    QFile file(logsDir + QString(m_appName) + dateSuffix + ".log");
    QFileInfo info(file);
    // 如果日志超过限制则重命名为其他文件名，不影响新日志保存
    if (info.size() > MAX_LOG_FILE_SIZE)
    {
        QString dateTimeSuffix = QDateTime::currentDateTime().toString("_yyyy_MM_dd_hh_mm_ss");
        file.rename(logsDir + QString(m_appName) + dateTimeSuffix + ".log");
    }

    if (file.open(QIODevice::ReadWrite | QIODevice::Append | QFile::Text))
    {
        QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
        file.write("[" + currentTime.toUtf8() + "] - ");
        file.write(log);
        file.write("\n");
        file.flush();
        file.close();
    }

    mutex.unlock();
}
